﻿#include "tcpservertunnel.h"
#include "tunnelcallback.h"

#include <net/netwriting.h>
#include <net/tcpserver.h>

#include <QThread>
#include "QsLog.h"

QNET_USING_NAMESPACE
TcpServerTunnel::TcpServerTunnel(const IPFiveTuple &ipTuple)
    : m_ipTuple(ipTuple)
{
    m_session = Q_NULLPTR;
    m_server = Q_NULLPTR;
    m_state = false;
    m_innerThread = Q_NULLPTR;

    static int id = qRegisterMetaType<QSharedPointer<NetWriting>>("QSharedPointer<NetWriting>");
    Q_UNUSED(id)
}

TcpServerTunnel::~TcpServerTunnel()
{
}

bool TcpServerTunnel::build()
{
    if(m_server)
    {
        m_server->deleteLater();
    }
    m_server = new TcpServer(this);
    bool ok = m_server->listen(m_ipTuple.localAddr(), m_ipTuple.localPort());
    // 监听成功，启动线程。
    if(ok)
    {
        if(m_innerThread)
        {
            m_innerThread->deleteLater();
        }
        m_innerThread = new QThread;
        QObject::connect(m_innerThread, &QThread::finished, m_innerThread, &QThread::deleteLater);
        QObject::connect(m_innerThread, &QThread::finished, m_server, &TcpServer::deleteLater);

        m_innerThread->start();
        m_server->moveToThread(m_innerThread);
    }else
    {
        m_server->deleteLater();
        m_server = Q_NULLPTR;
    }
    return ok;
}

void TcpServerTunnel::destory()
{
    if(m_server)
    {
        m_server->setListener(Q_NULLPTR);
    }
    if(m_innerThread){
        m_innerThread->exit();
    }
}

int TcpServerTunnel::write(QByteArray &src)
{
    if(m_state && m_session)
    {
        NetWriting *pWriting = new NetWriting;
        pWriting->setData(src);
        QSharedPointer<NetWriting> writing( pWriting, &NetWriting::deleteLater);
        return m_session->write(writing);
    }
    return false;
}

bool TcpServerTunnel::state()
{
    return m_state;
}

void TcpServerTunnel::disConnect()
{
    if(m_state && m_session)
    {
        m_session->setReading(Q_NULLPTR);
        m_session->close();
        return;
    }
}

void TcpServerTunnel::fetchTuple(IPFiveTuple &tuple)
{
    tuple.setType(IPFiveTuple::Type_TcpServer);
    if(m_session)
    {
        tuple.setLocalPort(m_session->localPort());
        tuple.setLocalAddr(m_session->localIp());
        tuple.setRemotePort(m_session->remotePort());
        tuple.setRemoteAddr(m_session->remoteIp());
    }
}

void TcpServerTunnel::onStateChanged(TcpSession *session, bool connected)
{
    QString msg;
    QTextStream stream(&msg);
    stream << QString(QObject::tr("conencted:%1;m_state:%2.session:%3"))
              .arg(connected).arg(m_state).arg(quint64(session));
    QLOG_DEBUG() << msg;

    if(m_state && connected) // 当前状态已连接，不再接收其它连接。
    {
        QLOG_DEBUG() <<  QObject::tr(" Detect exist one test, disconenct!");
        session->close(); // 服务端隧道仅同时提供一个连接上的服务。
        return;
    }

    if(connected)
    {
        m_state = connected;
        m_session = session;
        m_session->setReading(this);
    }else if(m_session == session)
    {
        m_state = connected; // 状态修改。
        m_session->setReading(Q_NULLPTR);
        m_session = Q_NULLPTR;
    }else
    {
        return; // 其它（非当前工作）连接的断开不处理。
    }

    auto func = [connected](TunnelCallback *item)->void {item->onStateChange(connected);};
    execEach(func);
}

void TcpServerTunnel::onError(QAbstractSocket::SocketError)
{

}

void TcpServerTunnel::onProc(const QByteArray &arry)
{
    auto func = [=](TunnelCallback *item)->void {item->onProc(arry);};
    execEach(func);
}
